home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / termsorc.lha / Extras / Source / gtlayout-source.lha / LTP_PopupClass.c < prev    next >
C/C++ Source or Header  |  1995-09-26  |  26KB  |  1,180 lines

  1. /*  GadTools layout toolkit
  2. **
  3. **  Copyright © 1993-1995 by Olaf `Olsen' Barthel
  4. **  Freely distributable.
  5. **
  6. **    :ts=4
  7. */
  8.  
  9. #include "gtlayout_global.h"
  10.  
  11. //#define DB(x)    x
  12. #define DB(x)    ;
  13.  
  14. #if defined(DO_POPUP_KIND) && defined(DO_BOOPSI_KIND)
  15.  
  16. #define PIF_SingleActive    (1 << 0)
  17. #define PIF_ArrowUp            (1 << 1)
  18. #define PIF_ArrowDown        (1 << 2)
  19. /*    // Intuition ghosts images all by itself
  20. STATIC VOID __regargs
  21. DrawDisabled(struct RastPort *RPort,UWORD Left,UWORD Top,UWORD Width,UWORD Height,UWORD *Pens)
  22. {
  23.     SetAPen(RPort,Pens[BLOCKPEN]);
  24.     SetDrMd(RPort,JAM1);
  25.  
  26.     SetAfPt(RPort,(UWORD *)&ghostingPat,1);
  27.     RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
  28.     SetAfPt(RPort,NULL,0);
  29. }
  30. */
  31. STATIC VOID __regargs
  32. DrawArrow(struct RastPort *RPort,UWORD Left,UWORD Top,LONG ArrowWidth,LONG ArrowHeight,WORD Dir)
  33. {
  34.     if(Dir < 0)
  35.     {
  36.         LONG i,Width,Start;
  37.  
  38.         for(i = 0 ; i < ArrowHeight ; i++)
  39.         {
  40.             Width = ((ArrowWidth * (i + 1)) / ArrowHeight) & ~1;
  41.  
  42.             if(Width < ArrowWidth)
  43.                 Width++;
  44.  
  45.             Start = Left + (ArrowWidth - Width) / 2;
  46.  
  47.             Move(RPort,Start,Top + i);
  48.             Draw(RPort,Start + Width - 1,Top + i);
  49.         }
  50.     }
  51.     else
  52.     {
  53.         LONG i,Width,Start;
  54.  
  55.         for(i = 0 ; i < ArrowHeight ; i++)
  56.         {
  57.             Width = ((ArrowWidth * (i + 1)) / ArrowHeight) & ~1;
  58.  
  59.             if(Width < ArrowWidth)
  60.                 Width++;
  61.  
  62.             Start = Left + (ArrowWidth - Width) / 2;
  63.  
  64.             Move(RPort,Start,Top + ArrowHeight - 1 - i);
  65.             Draw(RPort,Start + Width - 1,Top + ArrowHeight - 1 - i);
  66.         }
  67.     }
  68. }
  69.  
  70. STATIC VOID __regargs
  71. DrawContainer(struct RastPort *RPort,UWORD Left,UWORD Top,UWORD Width,UWORD Height,struct GadgetInfo *GadgetInfo,PopInfo *Info,BOOL Highlight,BOOL Disabled)
  72. {
  73.     UWORD     Shine,Shadow,Txt,Fill;
  74.     UWORD    *Pens;
  75.  
  76.     Pens = GadgetInfo->gi_DrInfo->dri_Pens;
  77.  
  78.     if(Highlight)
  79.     {
  80.         Shine    = Pens[SHADOWPEN];
  81.         Shadow    = Pens[SHINEPEN];
  82.         Txt        = Pens[FILLTEXTPEN];
  83.         Fill    = Pens[FILLPEN];
  84.     }
  85.     else
  86.     {
  87.         Shine    = Pens[SHINEPEN];
  88.         Shadow    = Pens[SHADOWPEN];
  89.         Txt        = Pens[TEXTPEN];
  90.         Fill    = Pens[BACKGROUNDPEN];
  91.     }
  92.  
  93.     SetDrMd(RPort,JAM1);
  94.  
  95.     SetAPen(RPort,Fill);
  96.     RectFill(RPort,Left + 2,Top + 1,Left + Width - 3,Top + Height - 2);
  97.  
  98.     SetAPen(RPort,Shine);
  99.     Move(RPort,Left + 1,Top + 1);
  100.     Draw(RPort,Left + 1,Top + Height - 2);
  101.     Draw(RPort,Left,Top + Height - 1);
  102.     Draw(RPort,Left,Top);
  103.     Draw(RPort,Left + Width - 2,Top);
  104.  
  105.     SetAPen(RPort,Shadow);
  106.     Move(RPort,Left + Width - 2,Top + Height - 2);
  107.     Draw(RPort,Left + Width - 2,Top + 1);
  108.     Draw(RPort,Left + Width - 1,Top);
  109.     Draw(RPort,Left + Width - 1,Top + Height - 1);
  110.     Draw(RPort,Left + 1,Top + Height - 1);
  111.  
  112.     SetAPen(RPort,Pens[SHADOWPEN]);
  113.     Move(RPort,Left + Info->MarkLeft,Top + 2);
  114.     Draw(RPort,Left + Info->MarkLeft,Top + Height - 3);
  115.  
  116.     SetAPen(RPort,Pens[SHINEPEN]);
  117.     Move(RPort,Left + Info->MarkLeft + 1,Top + 2);
  118.     Draw(RPort,Left + Info->MarkLeft + 1,Top + Height - 3);
  119.  
  120.     SetFont(RPort,Info->Font);
  121.     SetAPen(RPort,Txt);
  122.  
  123.     DrawArrow(RPort,Left + 4,Top + Info->ArrowTop,Info->ArrowWidth,Info->ArrowHeight,1);
  124.  
  125.     Move(RPort,Left + Info->LabelLeft,Top + Info->LabelBase);
  126.     Text(RPort,Info->Labels[Info->Active],Info->ActiveLen);
  127. /*    // Intuition ghosts images all by itself
  128.     if(Disabled)
  129.         DrawDisabled(RPort,Left,Top,Width,Height,Pens);
  130. */
  131. }
  132.  
  133. STATIC VOID __regargs
  134. DrawOneBox(PopInfo *Info,UWORD Top,STRPTR Label)
  135. {
  136.     struct RastPort    *RPort;
  137.     LONG             Len;
  138.  
  139.     RPort = Info->Window->RPort;
  140.  
  141.     if((Len = strlen(Label)) > Info->MaxLen)
  142.         Len = Info->MaxLen;
  143.  
  144.     Move(RPort,6,Top + Info->LineBase);
  145.     Text(RPort,Label,Len);
  146. }
  147.  
  148. STATIC VOID __regargs
  149. DrawOneGlyph(PopInfo *Info,UWORD Top,WORD Dir,UWORD *Pens)
  150. {
  151.     struct RastPort *RPort;
  152.  
  153.     RPort = Info->Window->RPort;
  154.  
  155.     if(Pens)
  156.     {
  157.         SetAPen(RPort,Info->MenuBack);
  158.         RectFill(RPort,4,Top,4 + Info->SingleWidth - 1,Top + Info->SingleHeight - 1);
  159.         SetAPen(RPort,Info->MenuText);
  160.     }
  161.  
  162.     DrawArrow(RPort,6,Top + Info->ArrowTop,Info->ArrowWidth,Info->ArrowHeight,Dir);
  163. }
  164.  
  165. STATIC VOID __regargs
  166. BoxRender(PopInfo *Info,UWORD *Pens,LONG Active,BOOL FullRefresh,BOOL Highlight,WORD Dir)
  167. {
  168.     struct RastPort *RPort = Info->Window->RPort;
  169.  
  170.     if(FullRefresh)
  171.     {
  172.         LONG Index,Top,Width,Height;
  173.  
  174.         SetAPen(RPort,Info->MenuBack);
  175.         SetDrMd(RPort,JAM1);
  176.  
  177.         Width    = Info->Window->Width;
  178.         Height    = Info->Window->Height;
  179.  
  180.         RectFill(RPort,2,1,Width - 3,Height - 2);
  181.  
  182.         SetAPen(RPort,Info->MenuText);
  183.  
  184.         Move(RPort,1,1);
  185.         Draw(RPort,1,Height - 2);
  186.         Draw(RPort,0,Height - 2);
  187.         Draw(RPort,0,0);
  188.         Draw(RPort,Width - 1,0);
  189.  
  190.         Move(RPort,0,Height - 1);
  191.         Draw(RPort,Width - 1,Height - 1);
  192.         Draw(RPort,Width - 1,1);
  193.         Draw(RPort,Width - 2,1);
  194.         Draw(RPort,Width - 2,Height - 2);
  195.  
  196.         Index    = Info->TopMost;
  197.         Top        = 2;
  198.         Height    = Info->BoxHeight;
  199.  
  200.         Info->Flags &= ~(PIF_ArrowUp | PIF_ArrowDown);
  201.  
  202.         if(Info->TopMost > 0 && Active != Info->TopMost && Info->BoxLines > 2)
  203.         {
  204.             Info->Flags |= PIF_ArrowUp;
  205.  
  206.             Index    += 1;
  207.             Top        += Info->SingleHeight;
  208.             Height    -= Info->SingleHeight;
  209.         }
  210.  
  211.         if(Info->TopMost + Info->BoxLines < Info->NumLabels && Active != Info->TopMost + Info->BoxLines - 1 && Info->BoxLines > 2)
  212.         {
  213.             Info->Flags |= PIF_ArrowDown;
  214.  
  215.             Height -= Info->SingleHeight;
  216.         }
  217.  
  218.         for( ; Index < Info->NumLabels && Height > 0 ; Index++, Top += Info->SingleHeight, Height -= Info->SingleHeight)
  219.         {
  220.             if(Index == Active)
  221.             {
  222.                 SetAPen(RPort,Info->MenuBackSelect);
  223.                 RectFill(RPort,4,Top,4 + Info->SingleWidth - 1,Top + Info->SingleHeight - 1);
  224.  
  225.                 SetAPen(RPort,Info->MenuTextSelect);
  226.                 DrawOneBox(Info,Top,Info->Labels[Index]);
  227.  
  228.                 SetAPen(RPort,Info->MenuText);
  229.             }
  230.             else
  231.                 DrawOneBox(Info,Top,Info->Labels[Index]);
  232.         }
  233.  
  234.         if(Info->Flags & PIF_ArrowUp)
  235.             DrawOneGlyph(Info,2,-1,NULL);
  236.  
  237.         if(Info->Flags & PIF_ArrowDown)
  238.             DrawOneGlyph(Info,2 + (Info->BoxLines - 1) * Info->SingleHeight,1,NULL);
  239.  
  240.         Info->LastDrawn            = 2 + (Active - Info->TopMost) * Info->SingleHeight;
  241.         Info->LastLabelDrawn    = Info->Labels[Active];
  242.     }
  243.     else
  244.     {
  245.         if(Info->LastLabelDrawn)
  246.         {
  247.             LONG Top = Info->LastDrawn;
  248.  
  249.             SetDrMd(RPort,JAM1);
  250.  
  251.             SetAPen(RPort,Info->MenuBack);
  252.             RectFill(RPort,4,Top,4 + Info->SingleWidth - 1,Top + Info->SingleHeight - 1);
  253.  
  254.             SetAPen(RPort,Info->MenuText);
  255.             DrawOneBox(Info,Top,Info->LastLabelDrawn);
  256.         }
  257.  
  258.         Info->LastDrawn            = -1;
  259.         Info->LastLabelDrawn    = NULL;
  260.  
  261.         if(Active >= 0)
  262.         {
  263.             LONG Top,NewActive;
  264.  
  265.             NewActive    = Active - Info->TopMost;
  266.             Top            = 2 + NewActive * Info->SingleHeight;
  267.  
  268.             if(Top >= 2 && Top < Info->BoxHeight + 2)
  269.             {
  270.                 UWORD Pen;
  271.  
  272.                 if(Dir != 0)
  273.                     Highlight = FALSE;
  274.  
  275.                 if(Highlight)
  276.                 {
  277.                     Pen = Info->MenuBackSelect;
  278.  
  279.                     Info->LastDrawn            = Top;
  280.                     Info->LastLabelDrawn    = Info->Labels[Active];
  281.                 }
  282.                 else
  283.                     Pen = Info->MenuBack;
  284.  
  285.                 SetDrMd(RPort,JAM1);
  286.  
  287.                 SetAPen(RPort,Pen);
  288.                 RectFill(RPort,4,Top,4 + Info->SingleWidth - 1,Top + Info->SingleHeight - 1);
  289.  
  290.                 if(Highlight)
  291.                     Pen = Info->MenuTextSelect;
  292.                 else
  293.                     Pen = Info->MenuText;
  294.  
  295.                 SetAPen(RPort,Pen);
  296.  
  297.                 if(Dir == 0)
  298.                     DrawOneBox(Info,Top,Info->Labels[Active]);
  299.                 else
  300.                     DrawOneGlyph(Info,Top,Dir,NULL);
  301.             }
  302.         }
  303.     }
  304. }
  305.  
  306. STATIC ULONG __regargs
  307. InputMethod(struct IClass *class,struct Gadget *gadget,struct gpInput *InputInfo)
  308. {
  309.     PopInfo    *Info    = INST_DATA(class,gadget);
  310.     ULONG     Result    = GMR_MEACTIVE;
  311.     BOOL     Done    = FALSE;
  312.  
  313.     if(InputInfo->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE)
  314.     {
  315.         UWORD Code = InputInfo->gpi_IEvent->ie_Code;
  316.  
  317.         if(Code == MENUDOWN)
  318.         {
  319.             Result    = GMR_NOREUSE;
  320.             Done    = TRUE;
  321.  
  322.             Info->Active = Info->InitialActive;
  323.         }
  324.         else
  325.         {
  326.             if(Code == SELECTUP)
  327.             {
  328.                 Done = TRUE;
  329.  
  330.                 if(Info->Active < 0)
  331.                 {
  332.                     Result = GMR_NOREUSE;
  333.  
  334.                     Info->Active = Info->InitialActive;
  335.                 }
  336.                 else
  337.                 {
  338.                     LONG Len;
  339.  
  340.                     Result = GMR_REUSE | GMR_VERIFY;
  341.  
  342.                     if(Info->Flags & PIF_SingleActive)
  343.                     {
  344.                         UWORD Width,Height;
  345.                         WORD x,y;
  346.  
  347.                         x = InputInfo->gpi_Mouse . X;
  348.                         y = InputInfo->gpi_Mouse . Y;
  349.  
  350.                         Width    = gadget->Width;
  351.                         Height    = gadget->Height;
  352.  
  353.                         if(x >= 0 && y >= 0 && x < Width && y < Height)
  354.                         {
  355.                             if(InputInfo->gpi_IEvent->ie_Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  356.                                 Info->Active--;
  357.                             else
  358.                                 Info->Active++;
  359.  
  360.                             if(Info->Active >= Info->NumLabels)
  361.                                 Info->Active = 0;
  362.                             else
  363.                             {
  364.                                 if(Info->Active < 0)
  365.                                     Info->Active = Info->NumLabels - 1;
  366.                             }
  367.                         }
  368.                         else
  369.                         {
  370.                             Result = GMR_NOREUSE;
  371.  
  372.                             Info->Active = Info->InitialActive;
  373.                         }
  374.                     }
  375.  
  376.                     Len = strlen(Info->Labels[Info->Active]);
  377.  
  378.                     if(Len > Info->MaxLen)
  379.                         Len = Info->MaxLen;
  380.  
  381.                     Info->ActiveLen = Len;
  382.  
  383.                     *InputInfo->gpi_Termination = Info->Active;
  384.                 }
  385.             }
  386.             else
  387.             {
  388.                 if(Info->Flags & PIF_SingleActive)
  389.                 {
  390.                     UWORD Left,Top,Width,Height;
  391.                     WORD x,y;
  392.  
  393.                     x = InputInfo->gpi_Mouse . X;
  394.                     y = InputInfo->gpi_Mouse . Y;
  395.  
  396.                     Left    = gadget->LeftEdge;
  397.                     Top        = gadget->TopEdge;
  398.                     Width    = gadget->Width;
  399.                     Height    = gadget->Height;
  400.  
  401.                     if(x < 0 || y < 0 || x >= Width || y >= Height)
  402.                     {
  403.                         if(gadget->Flags & GFLG_SELECTED)
  404.                         {
  405.                             struct RastPort    *RPort;
  406.  
  407.                             if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  408.                             {
  409.                                 DrawContainer(RPort,Left,Top,Width,Height,InputInfo->gpi_GInfo,Info,FALSE,FALSE);
  410.  
  411.                                 gadget->Flags &= ~GFLG_SELECTED;
  412.  
  413.                                 ReleaseGIRPort(RPort);
  414.                             }
  415.                         }
  416.                     }
  417.                     else
  418.                     {
  419.                         if(!(gadget->Flags & GFLG_SELECTED))
  420.                         {
  421.                             struct RastPort    *RPort;
  422.  
  423.                             if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  424.                             {
  425.                                 DrawContainer(RPort,Left,Top,Width,Height,InputInfo->gpi_GInfo,Info,TRUE,FALSE);
  426.  
  427.                                 gadget->Flags |= GFLG_SELECTED;
  428.  
  429.                                 ReleaseGIRPort(RPort);
  430.                             }
  431.                         }
  432.                     }
  433.                 }
  434.             }
  435.         }
  436.  
  437.         if(Done)
  438.         {
  439.             struct RastPort    *RPort;
  440.  
  441.             if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  442.             {
  443.                 DrawContainer(RPort,gadget->LeftEdge,gadget->TopEdge,gadget->Width,gadget->Height,InputInfo->gpi_GInfo,Info,FALSE,FALSE);
  444.  
  445.                 ReleaseGIRPort(RPort);
  446.             }
  447.  
  448.             if(Info->Window)
  449.             {
  450.                 CloseWindow(Info->Window);
  451.                 Info->Window = NULL;
  452.             }
  453.  
  454.             Info->Flags &= ~PIF_SingleActive;
  455.         }
  456.     }
  457.  
  458.     if(!Done && Info->Window)
  459.     {
  460.         LONG    NewActive = 0;
  461.         WORD    x,y;
  462.         WORD    Dir = 0;
  463.         UWORD    From,To;
  464.  
  465.         x = InputInfo->gpi_GInfo->gi_Screen->MouseX - Info->BoxLeft;
  466.         y = InputInfo->gpi_GInfo->gi_Screen->MouseY - Info->BoxTop;
  467.  
  468.         if(x < 0 || x >= Info->BoxWidth)
  469.             NewActive = -1;
  470.         else
  471.         {
  472.             UWORD Margin;
  473.  
  474.             if(Info->Flags & (PIF_ArrowUp | PIF_ArrowDown))
  475.                 Margin = Info->SingleHeight;
  476.             else
  477.                 Margin = (Info->SingleHeight + 3) / 4;
  478.  
  479.                 // Scroll up?
  480.  
  481.             if(y < Margin)
  482.             {
  483.                 if(y < 0)
  484.                     NewActive = -1;
  485.                 else
  486.                 {
  487.                         // Topmost line concealed?
  488.  
  489.                     if(Info->TopMost > 0)
  490.                     {
  491.                         Info->TopMost--;
  492.  
  493.                         From    = 2;
  494.                         To        = 2 + Info->BoxHeight - 1;
  495.  
  496.                         Dir = -Info->SingleHeight;
  497.                     }
  498.                 }
  499.             }
  500.             else
  501.             {
  502.                 LONG Last;
  503.  
  504.                 Last = Info->NumLabels - Info->TopMost;
  505.  
  506.                 if(Last < Info->BoxLines)
  507.                     Last = Last * Info->SingleHeight;
  508.                 else
  509.                     Last = Info->BoxHeight;
  510.  
  511.                     // Scroll up?
  512.  
  513.                 if(y >= Last - Margin)
  514.                 {
  515.                     if(y >= Last)
  516.                         NewActive = -1;
  517.                     else
  518.                     {
  519.                             // Last line concealed?
  520.  
  521.                         if(Info->TopMost + Info->BoxLines < Info->NumLabels)
  522.                         {
  523.                             Info->TopMost++;
  524.  
  525.                             From    = 2;
  526.                             To        = 2 + Info->BoxHeight - 1;
  527.  
  528.                             Dir = Info->SingleHeight;
  529.                         }
  530.                     }
  531.                 }
  532.             }
  533.  
  534.             if(NewActive != -1)
  535.             {
  536.                 NewActive = Info->TopMost + y / Info->SingleHeight;
  537.  
  538.                 if(NewActive < 0)
  539.                     NewActive = 0;
  540.                 else
  541.                 {
  542.                     if(NewActive >= Info->NumLabels)
  543.                         NewActive = Info->NumLabels - 1;
  544.                 }
  545.             }
  546.         }
  547.  
  548.         if(NewActive != Info->Active || Dir != 0)
  549.         {
  550.             WORD     Arrow;
  551.             UWORD    *Pens = InputInfo->gpi_GInfo->gi_DrInfo->dri_Pens;
  552.  
  553.             if(Dir != 0)
  554.             {
  555.                 struct RastPort *RPort = Info->Window->RPort;
  556.  
  557.                 Arrow = (NewActive == Info->TopMost) ? -1 : 1;
  558.  
  559.                 BoxRender(Info,Pens,-1,FALSE,FALSE,0);
  560.  
  561.                 if(Info->Flags & PIF_ArrowUp)
  562.                     From += Info->SingleHeight;
  563.  
  564.                 if(Info->Flags & PIF_ArrowDown)
  565.                     To -= Info->SingleHeight;
  566.  
  567.                 SetBPen(RPort,Pens[BACKGROUNDPEN]);
  568.                 ScrollRaster(RPort,0,Dir,4,From,4 + Info->BoxWidth - 1,To);
  569.  
  570.                 if(Dir < 0)
  571.                     BoxRender(Info,Pens,Info->TopMost + 1,FALSE,FALSE,0);
  572.                 else
  573.                     BoxRender(Info,Pens,Info->TopMost + Info->BoxLines - 2,FALSE,FALSE,0);
  574.  
  575.                 if(!Info->TopMost || Info->BoxLines < 3)
  576.                 {
  577.                     Info->Flags &= ~PIF_ArrowUp;
  578.  
  579.                     Arrow = 0;
  580.                 }
  581.                 else
  582.                 {
  583.                     if(!(Info->Flags & PIF_ArrowUp))
  584.                     {
  585.                         Info->Flags |= PIF_ArrowUp;
  586.  
  587.                         DrawOneGlyph(Info,2,-1,Pens);
  588.                     }
  589.                 }
  590.  
  591.                 if(Info->TopMost + Info->BoxLines >= Info->NumLabels || Info->BoxLines < 3)
  592.                 {
  593.                     Info->Flags &= ~PIF_ArrowDown;
  594.  
  595.                     Arrow = 0;
  596.                 }
  597.                 else
  598.                 {
  599.                     if(!(Info->Flags & PIF_ArrowDown))
  600.                     {
  601.                         Info->Flags |= PIF_ArrowDown;
  602.  
  603.                         DrawOneGlyph(Info,2 + (Info->BoxLines - 1) * Info->SingleHeight,1,Pens);
  604.                     }
  605.                 }
  606.             }
  607.             else
  608.                 Arrow = 0;
  609.  
  610.             Info->Active = NewActive;
  611.  
  612.             BoxRender(Info,Pens,NewActive,FALSE,TRUE,Arrow);
  613.         }
  614.     }
  615.  
  616.     return(Result);
  617. }
  618.  
  619. STATIC ULONG __regargs
  620. SetMethod(struct IClass *class,struct Gadget *gadget,struct opSet *SetInfo)
  621. {
  622.     PopInfo            *Info = INST_DATA(class,gadget);
  623.     struct TagItem    *This;
  624.     LONG             NewActive;
  625.     STRPTR            *NewLabels;
  626.     ULONG             Result;
  627.     UWORD             Flags = gadget -> Flags;
  628.     BOOL             NeedRefresh = FALSE;
  629.  
  630.     DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
  631.  
  632.     Result = DoSuperMethodA(class,(Object *)gadget,(Msg)SetInfo);
  633.  
  634.     if(This = FindTagItem(GA_Disabled,SetInfo->ops_AttrList))
  635.     {
  636.         if(This -> ti_Data && !(Flags & GFLG_DISABLED) || !This -> ti_Data && (Flags & GFLG_DISABLED))
  637.             NeedRefresh = TRUE;
  638.     }
  639.  
  640.     NewLabels = (STRPTR *)GetTagData(PIA_Labels,NULL,SetInfo->ops_AttrList);
  641.  
  642.     if(This = FindTagItem(PIA_Active,SetInfo->ops_AttrList))
  643.     {
  644.         LONG NumLabels = Info->NumLabels;
  645.  
  646.         if(NewLabels)
  647.             for(NumLabels = 0 ; NewLabels[NumLabels] ; NumLabels++);
  648.  
  649.         NewActive = (LONG)This->ti_Data;
  650.  
  651.         if(NewActive < 0)
  652.             NewActive = 0;
  653.         else
  654.         {
  655.             if(NewActive >= NumLabels)
  656.                 NewActive = NumLabels - 1;
  657.         }
  658.     }
  659.     else
  660.         NewActive = -1;
  661.  
  662.     if((NewActive != Info->Active && NewActive != -1) || NewLabels)
  663.     {
  664.         struct RastPort *RPort;
  665.  
  666.         if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
  667.         {
  668.             UWORD     Left,Top,Width;
  669.             LONG     Len;
  670.             STRPTR    *Labels;
  671.             LONG     NumLabels,MaxLen,ActiveLen;
  672.             UWORD    *Pens;
  673.  
  674.             if(NewLabels)
  675.             {
  676.                 struct TextExtent Extent;
  677.  
  678.                 for(NumLabels = MaxLen = 0 ; NewLabels[NumLabels] ; NumLabels++)
  679.                 {
  680.                     Len = TextFit(RPort,NewLabels[NumLabels],strlen(NewLabels[NumLabels]),&Extent,NULL,1,Info->MaxWidth,32767);
  681.  
  682.                     if(Len > MaxLen)
  683.                         MaxLen = Len;
  684.                 }
  685.  
  686.                 Labels = NewLabels;
  687.             }
  688.             else
  689.             {
  690.                 Labels        = Info->Labels;
  691.                 NumLabels    = Info->NumLabels;
  692.                 MaxLen        = Info->MaxLen;
  693.             }
  694.  
  695.             if(NewActive == -1)
  696.                 NewActive = Info->Active;
  697.  
  698.             if(NewActive >= NumLabels)
  699.                 NewActive = NumLabels - 1;
  700.  
  701.             Pens    = SetInfo->ops_GInfo->gi_DrInfo->dri_Pens;
  702.             Left    = gadget -> LeftEdge;
  703.             Top        = gadget -> TopEdge;
  704.  
  705.             SetFont(RPort,Info->Font);
  706.  
  707.             Len = strlen(Labels[NewActive]);
  708.  
  709.             if(Len > MaxLen)
  710.                 Len = MaxLen;
  711.  
  712.             ActiveLen = Len;
  713.  
  714.             Width = TextLength(RPort,Labels[NewActive],ActiveLen);
  715.  
  716.             SetDrMd(RPort,JAM2);
  717.  
  718.             if(Width < Info->MaxWidth)
  719.             {
  720.                 SetAPen(RPort,Pens[BACKGROUNDPEN]);
  721.                 RectFill(RPort,Left + Info->LabelLeft + Width,Top + Info->LabelTop,Left + Info->LabelLeft + Info->MaxWidth - 1,Top + Info->LabelTop + RPort->TxHeight - 1);
  722.             }
  723.  
  724.             SetAPen(RPort,Pens[TEXTPEN]);
  725.             SetBPen(RPort,Pens[BACKGROUNDPEN]);
  726.  
  727.             Move(RPort,Left + Info->LabelLeft,Top + Info->LabelBase);
  728.             Text(RPort,Labels[NewActive],ActiveLen);
  729.  
  730.             Info->Active    = NewActive;
  731.             Info->ActiveLen    = ActiveLen;
  732.  
  733.             if(NewLabels)
  734.             {
  735.                 Info->Labels    = Labels;
  736.                 Info->NumLabels    = NumLabels;
  737.                 Info->MaxLen    = MaxLen;
  738.             }
  739. /*            // Intuition ghosts images all by itself
  740.             if(((struct Gadget *)object) -> Flags & GFLG_DISABLED)
  741.             {
  742.                 UWORD Height;
  743.  
  744.                 Width    = ((struct Gadget *)object) -> Width;
  745.                 Height    = ((struct Gadget *)object) -> Height;
  746.  
  747.                 DrawDisabled(RPort,Left,Top,Width,Height,Pens);
  748.             }
  749. */
  750.             NeedRefresh = FALSE;
  751.  
  752.             ReleaseGIRPort(RPort);
  753.         }
  754.     }
  755.  
  756.     if(!(gadget -> Flags & GFLG_DISABLED) && (This = FindTagItem(PIA_Highlight,SetInfo->ops_AttrList)))
  757.     {
  758.         struct RastPort *RPort;
  759.  
  760.         if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
  761.         {
  762.             DrawContainer(RPort,gadget->LeftEdge,gadget->TopEdge,gadget->Width,gadget->Height,SetInfo->ops_GInfo,Info,This->ti_Data,FALSE);
  763.  
  764.             NeedRefresh = FALSE;
  765.  
  766.             ReleaseGIRPort(RPort);
  767.         }
  768.     }
  769.  
  770.     if(NeedRefresh)
  771.     {
  772.         struct RastPort *RPort;
  773.  
  774.         if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
  775.         {
  776.             DrawContainer(RPort,gadget->LeftEdge,gadget->TopEdge,gadget->Width,gadget->Height,SetInfo->ops_GInfo,Info,FALSE,gadget -> Flags & GFLG_DISABLED);
  777.  
  778.             ReleaseGIRPort(RPort);
  779.         }
  780.     }
  781.  
  782.     return(Result);
  783. }
  784.  
  785. STATIC ULONG __regargs
  786. RenderMethod(struct IClass *class,struct Gadget *gadget,struct gpRender *RenderInfo)
  787. {
  788.     PopInfo    *Info = INST_DATA(class,gadget);
  789.  
  790.     DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
  791.  
  792.     DrawContainer(RenderInfo->gpr_RPort,gadget->LeftEdge,gadget->TopEdge,gadget->Width,gadget->Height,RenderInfo->gpr_GInfo,Info,gadget->Flags & GFLG_SELECTED,gadget->Flags & GFLG_DISABLED);
  793.  
  794.     return(TRUE);
  795. }
  796.  
  797. STATIC ULONG __regargs
  798. DisposeMethod(struct IClass *class,Object *object,Msg msg)
  799. {
  800.     PopInfo *Info = INST_DATA(class,object);
  801.  
  802.     DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
  803.  
  804.     if(Info->Font)
  805.     {
  806.         CloseFont(Info->Font);
  807.         Info->Font = NULL;
  808.     }
  809.  
  810.     if(Info->Window)
  811.     {
  812.         CloseWindow(Info->Window);
  813.         Info->Window = NULL;
  814.     }
  815.  
  816.     return(DoSuperMethodA(class,object,msg));
  817. }
  818.  
  819. STATIC ULONG __regargs
  820. NewMethod(struct IClass *class,Object *object,struct opSet *SetInfo)
  821. {
  822.     DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
  823.  
  824.     if(object = (Object *)DoSuperMethodA(class,object,(Msg)SetInfo))
  825.     {
  826.         PopInfo            *Info = INST_DATA(class,object);
  827.         struct TagItem    *Item,*TagList = SetInfo -> ops_AttrList;
  828.         struct TextAttr    *Font;
  829.         LONG             Width,Height;
  830.  
  831.         Width = Height = 0;
  832.         Font = NULL;
  833.  
  834.         memset(Info,0,sizeof(PopInfo));
  835.  
  836.         while(Item = NextTagItem(&TagList))
  837.         {
  838.             switch(Item->ti_Tag)
  839.             {
  840.                 case GA_Width:
  841.                     Width = Item->ti_Data;
  842.                     break;
  843.  
  844.                 case GA_Height:
  845.                     Height = Item->ti_Data;
  846.                     break;
  847.  
  848.                 case PIA_Labels:
  849.                     Info->Labels = (STRPTR *)Item->ti_Data;
  850.                     break;
  851.  
  852.                 case PIA_Active:
  853.                     Info->Active = (LONG)Item->ti_Data;
  854.                     break;
  855.  
  856.                 case PIA_Font:
  857.                     Font = (struct TextAttr *)Item->ti_Data;
  858.                     break;
  859.             }
  860.         }
  861.  
  862.         if(Font && Info->Labels && Width && Height)
  863.         {
  864.             while(Info->Labels[Info->NumLabels])
  865.                 Info->NumLabels++;
  866.  
  867.             if(Info->NumLabels)
  868.             {
  869.                 if(Info->Font = OpenFont(Font))
  870.                 {
  871.                     struct RastPort __aligned RPort;
  872.  
  873.                     if(Info->Active < 0)
  874.                         Info->Active = 0;
  875.                     else
  876.                     {
  877.                         if(Info->Active >= Info->NumLabels)
  878.                             Info->Active = Info->NumLabels - 1;
  879.                     }
  880.  
  881.                     InitRastPort(&RPort);
  882.                     SetFont(&RPort,Info->Font);
  883.  
  884.                     Info->ArrowWidth    = (TextLength(&RPort,"M",1) & ~1) + 1;
  885.                     Info->ArrowHeight    = (2 * RPort.TxHeight) / 3;
  886.                     Info->ArrowTop        = (Height - Info->ArrowHeight) / 2;
  887.  
  888.                     Info->MarkLeft    = 4 + Info->ArrowWidth + 2;
  889.                     Info->MarkWidth    = Info->MarkLeft + 4;
  890.  
  891.                     Info->PopLeft    = Info->MarkWidth - 6;
  892.                     Info->PopWidth    = Width - Info->PopLeft;
  893.  
  894.                     Info->LabelTop    = (Height - RPort.TxHeight) / 2;
  895.                     Info->LabelLeft    = Info->MarkWidth;
  896.                     Info->LabelBase    = Info->LabelTop + RPort.TxBaseline;
  897.  
  898.                     Width    -= 6 + Info->MarkWidth + 6;
  899.                     Height    -= 2 + RPort.TxHeight + 2;
  900.  
  901.                     if(Width > 0 && Height >= 0)
  902.                     {
  903.                         struct TextExtent    Extent;
  904.                         LONG                i,Len,MaxLen;
  905.  
  906.                         for(i = MaxLen = 0 ; i < Info->NumLabels ; i++)
  907.                         {
  908.                             Len = TextFit(&RPort,Info->Labels[i],strlen(Info->Labels[i]),&Extent,NULL,1,Width,32767);
  909.  
  910.                             if(Len > MaxLen)
  911.                                 MaxLen = Len;
  912.                         }
  913.  
  914.                         if(MaxLen)
  915.                         {
  916.                             Len = strlen(Info->Labels[Info->Active]);
  917.  
  918.                             if(Len > MaxLen)
  919.                                 Len = MaxLen;
  920.  
  921.                             Info->ActiveLen = Len;
  922.  
  923.                             Info->MaxLen    = MaxLen;
  924.                             Info->MaxWidth    = Width;
  925.  
  926.                             return((ULONG)object);
  927.                         }
  928.                     }
  929.  
  930.                     CloseFont(Info->Font);
  931.                     Info->Font = NULL;
  932.                 }
  933.             }
  934.         }
  935.  
  936.         CoerceMethod(class,object,OM_DISPOSE);
  937.     }
  938.  
  939.     return(0);
  940. }
  941.  
  942. STATIC ULONG __regargs
  943. ActiveMethod(struct IClass *class,struct Gadget *gadget,struct gpInput *InputInfo)
  944. {
  945.     PopInfo            *Info = INST_DATA(class,gadget);
  946.     struct RastPort    *RPort;
  947.  
  948.     DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
  949.  
  950.     if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  951.     {
  952.         LONG Left,Top;
  953.  
  954.         Left    = gadget->LeftEdge;
  955.         Top        = gadget->TopEdge;
  956.  
  957.         Info->Window = NULL;
  958.  
  959.         if(Info->NumLabels > 2 && InputInfo->gpi_Mouse.X >= Info->MarkLeft)
  960.         {
  961.             UWORD SingleHeight,ScreenHeight,Width,Height;
  962.  
  963.             Info->Flags &= ~PIF_SingleActive;
  964.             Info->Window = NULL;
  965.  
  966.             SetFont(RPort,Info->Font);
  967.  
  968.             SingleHeight = gadget->Height;
  969.             ScreenHeight = InputInfo->gpi_GInfo->gi_Screen->Height;
  970.  
  971.             Info->LineTop    = (SingleHeight - RPort->TxHeight) / 2;
  972.             Info->LineBase    = Info->LineTop + RPort->TxBaseline;
  973.  
  974.             Width    = Info->PopWidth;
  975.             Height    = 2 + SingleHeight * Info->NumLabels + 2;
  976.  
  977.             while(Height > SingleHeight && Height > ScreenHeight)
  978.                 Height -= SingleHeight;
  979.  
  980.             if(Height > SingleHeight)
  981.             {
  982.                 LONG LeftEdge,TopEdge,TopMost;
  983.  
  984.                 LeftEdge    = InputInfo->gpi_GInfo->gi_Window->LeftEdge + Left + Info->PopLeft;
  985.                 TopEdge        = InputInfo->gpi_GInfo->gi_Window->TopEdge + Top + Info->LabelTop - (2 + Info->LineTop + Info->Active * SingleHeight);
  986.                 TopMost        = 0;
  987.  
  988.                 while(TopEdge < 0 && TopMost < Info->NumLabels)
  989.                 {
  990.                     TopEdge    += SingleHeight;
  991.                     TopMost    += 1;
  992.                 }
  993.  
  994.                 if(TopEdge >= 0 && TopMost < Info->NumLabels)
  995.                 {
  996.                     while(Height > SingleHeight && TopEdge + Height > ScreenHeight)
  997.                         Height -= SingleHeight;
  998.  
  999.                     if(Height > SingleHeight && TopEdge + Height <= ScreenHeight)
  1000.                     {
  1001.                         ReleaseGIRPort(RPort);
  1002.  
  1003.                         if(Info->Window = OpenWindowTags(NULL,
  1004.                             WA_Left,            LeftEdge,
  1005.                             WA_Top,                TopEdge,
  1006.                             WA_Width,            Width,
  1007.                             WA_Height,            Height,
  1008.                             WA_SimpleRefresh,    TRUE,
  1009.                             WA_NoCareRefresh,    TRUE,
  1010.                             WA_AutoAdjust,        FALSE,
  1011.                             WA_CustomScreen,    InputInfo->gpi_GInfo->gi_Screen,
  1012.                             WA_Borderless,        TRUE,
  1013.  
  1014.                             V39 ? WA_BackFill : TAG_IGNORE,LAYERS_NOBACKFILL,
  1015.                         TAG_DONE))
  1016.                         {
  1017.                             UWORD *Pens = InputInfo->gpi_GInfo->gi_DrInfo->dri_Pens;
  1018.  
  1019.                             Info->TopMost        = TopMost;
  1020.  
  1021.                             Info->BoxLeft        = LeftEdge + 4;
  1022.                             Info->BoxTop        = TopEdge + 2;
  1023.                             Info->BoxWidth        = Width - 8;
  1024.                             Info->BoxHeight        = Height - 4;
  1025.  
  1026.                             Info->BoxLines        = Info->BoxHeight / SingleHeight;
  1027.  
  1028.                             Info->SingleWidth    = Width - 8;
  1029.                             Info->SingleHeight    = SingleHeight;
  1030.  
  1031.                             if(V39)
  1032.                             {
  1033.                                 STATIC BYTE RenderPens[] =
  1034.                                 {
  1035.                                     BACKGROUNDPEN,
  1036.                                     FILLPEN,
  1037.                                     TEXTPEN,
  1038.                                     FILLTEXTPEN,
  1039.                                     SHADOWPEN,
  1040.                                     SHINEPEN,
  1041.                                     BARDETAILPEN,
  1042.                                     BARBLOCKPEN
  1043.                                     -1
  1044.                                 };
  1045.  
  1046.                                 UWORD i,Pen,Max = 0;
  1047.  
  1048.                                 Info->MenuText            = Pens[BARDETAILPEN];
  1049.                                 Info->MenuBack            = Pens[BARBLOCKPEN];
  1050.                                 Info->MenuTextSelect    = Pens[BARBLOCKPEN];
  1051.                                 Info->MenuBackSelect    = Pens[BARDETAILPEN];
  1052.  
  1053.                                 for(i = 0 ; RenderPens[i] != -1 ; i++)
  1054.                                 {
  1055.                                     if((Pen = Pens[RenderPens[i]]) > Max)
  1056.                                         Max = Pen;
  1057.                                 }
  1058.  
  1059.                                 SetMaxPen(Info->Window->RPort,Max);
  1060.                             }
  1061.                             else
  1062.                             {
  1063.                                 Info->MenuText            = Pens[DETAILPEN];
  1064.                                 Info->MenuBack            = Pens[BLOCKPEN];
  1065.                                 Info->MenuTextSelect    = ~Pens[DETAILPEN];
  1066.                                 Info->MenuBackSelect    = ~Pens[BLOCKPEN];
  1067.                             }
  1068.  
  1069.                             SetFont(Info->Window->RPort,Info->Font);
  1070.                         }
  1071.  
  1072.                         if(!(RPort = ObtainGIRPort(InputInfo->gpi_GInfo)))
  1073.                         {
  1074.                             if(Info->Window)
  1075.                             {
  1076.                                 CloseWindow(Info->Window);
  1077.                                 Info->Window = NULL;
  1078.                             }
  1079.                         }
  1080.                     }
  1081.                 }
  1082.             }
  1083.         }
  1084.  
  1085.         if(!Info->Window)
  1086.             Info->Flags |= PIF_SingleActive;
  1087.  
  1088.         if(((Info->Flags & PIF_SingleActive) || Info->Window) && RPort)
  1089.         {
  1090.             UWORD Width,Height;
  1091.  
  1092.             Info->InitialActive = Info->Active;
  1093.  
  1094.             Width    = gadget->Width;
  1095.             Height    = gadget->Height;
  1096.  
  1097.             DrawContainer(RPort,Left,Top,Width,Height,InputInfo->gpi_GInfo,Info,TRUE,FALSE);
  1098.  
  1099.             ReleaseGIRPort(RPort);
  1100.  
  1101.             if(Info->Window)
  1102.                 BoxRender(Info,InputInfo->gpi_GInfo->gi_DrInfo->dri_Pens,Info->Active,TRUE,TRUE,0);
  1103.  
  1104.             return(GMR_MEACTIVE);
  1105.         }
  1106.  
  1107.         if(RPort)
  1108.             ReleaseGIRPort(RPort);
  1109.     }
  1110.  
  1111.     return(GMR_NOREUSE);
  1112. }
  1113.  
  1114. STATIC ULONG __regargs
  1115. InactiveMethod(struct IClass *class,struct Gadget *gadget,struct gpGoInactive *InactiveInfo)
  1116. {
  1117.     PopInfo *Info = INST_DATA(class,gadget);
  1118.  
  1119.     DB(kprintf("%s %ld\n",__FUNC__,__LINE__));
  1120.  
  1121.     if(Info->Window || (Info->Flags & PIF_SingleActive))
  1122.     {
  1123.         struct RastPort    *RPort;
  1124.  
  1125.         if(RPort = ObtainGIRPort(InactiveInfo->gpgi_GInfo))
  1126.         {
  1127.             DrawContainer(RPort,gadget->LeftEdge,gadget->TopEdge,gadget->Width,gadget->Height,InactiveInfo->gpgi_GInfo,Info,FALSE,FALSE);
  1128.  
  1129.             ReleaseGIRPort(RPort);
  1130.         }
  1131.  
  1132.         if(Info->Window)
  1133.         {
  1134.             CloseWindow(Info->Window);
  1135.             Info->Window = NULL;
  1136.         }
  1137.  
  1138.         Info->Flags &= ~PIF_SingleActive;
  1139.     }
  1140.  
  1141.     return(0);
  1142. }
  1143.  
  1144. ULONG __saveds __asm
  1145. LTP_PopupClassDispatcher(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg)
  1146. {
  1147.     switch(msg->MethodID)
  1148.     {
  1149.         case OM_NEW:
  1150.             return(NewMethod(class,object,(struct opSet *)msg));
  1151.  
  1152.         case OM_UPDATE:
  1153.         case OM_SET:
  1154.             return(SetMethod(class,(struct Gadget *)object,(struct opSet *)msg));
  1155.  
  1156.         case OM_DISPOSE:
  1157.             return(DisposeMethod(class,object,msg));
  1158.  
  1159.         case GM_RENDER:
  1160.             return(RenderMethod(class,(struct Gadget *)object,(struct gpRender *)msg));
  1161.  
  1162.         case GM_HITTEST:
  1163.             return(GMR_GADGETHIT);
  1164.  
  1165.         case GM_GOINACTIVE:
  1166.             return(InactiveMethod(class,(struct Gadget *)object,(struct gpGoInactive *)msg));
  1167.  
  1168.         case GM_GOACTIVE:
  1169.             return(ActiveMethod(class,(struct Gadget *)object,(struct gpInput *)msg));
  1170.  
  1171.         case GM_HANDLEINPUT:
  1172.             return(InputMethod(class,(struct Gadget *)object,(struct gpInput *)msg));
  1173.  
  1174.         default:
  1175.             return(DoSuperMethodA(class,object,msg));
  1176.     }
  1177. }
  1178.  
  1179. #endif    // defined(DO_POPUP_KIND) && defined(DO_BOOPSI_KIND)
  1180.